<?php

namespace App\Http\Services\FormBuilder\Elements;

abstract class Element
{
    protected $attributes = [];

    protected $label = false;

    protected $fieldWidth;

    protected $widthTranslation = [
        '',
        'col-1',
        'col-2',
        'col-3',
        'col-4',
        'col-5',
        'col-6',
        'col-7',
        'col-8',
        'col-9',
        'col-10',
        'col-11',
        'col-12'
    ];

    protected function getPrimaryControl()
    {
        return $this;
    }

    protected function setAttribute($attribute, $value = null)
    {
        if (is_null($value)) {
            return;
        }

        $this->attributes[$attribute] = $value;
    }

    protected function removeAttribute($attribute)
    {
        unset($this->attributes[$attribute]);
    }

    public function getAttribute($attribute)
    {
        return @$this->attributes[$attribute];
    }

    public function hasAttribute($attribute)
    {
        return isset($this->attributes[$attribute]);
    }

    public function data($attribute, $value)
    {
        $this->setAttribute('data-' . $attribute, $value);

        return $this;
    }

    public function attribute($attribute, $value)
    {
        $this->setAttribute($attribute, $value);

        return $this;
    }

    public function attributes($attributes)
    {

        foreach ($attributes as $key => $value) {

            if ($key == 'class') {
                return $this->addClass($value);
            }
            if ($key == 'options') {
                $this->setOptions($value);
            }

            $this->setAttribute($key, $value);
        }
        return $this;
    }

    public function clear($attribute)
    {
        if (!isset($this->attributes[$attribute])) {
            return $this;
        }

        $this->removeAttribute($attribute);

        return $this;
    }

    public function addClass($class)
    {
        if (!$class) {
            return $this;
        }

        if (isset($this->attributes['class'])) {

            $existingClasses = explode(' ', $this->attributes['class']);
            $newClasses      = explode(' ', $class);

            $class = implode(' ', array_unique(array_merge($existingClasses, $newClasses)));
        }

        $this->setAttribute('class', $class);

        return $this;
    }

    public function removeClass($class)
    {
        if (!isset($this->attributes['class'])) {
            return $this;
        }

        $class = trim(str_replace($class, '', $this->attributes['class']));
        if ($class == '') {
            $this->removeAttribute('class');

            return $this;
        }

        $this->setAttribute('class', $class);

        return $this;
    }

    public function id($id)
    {
        $this->setId($id);

        return $this;
    }

    protected function setId($id)
    {
        $this->setAttribute('id', $id);
    }

    public function label($label)
    {
        $this->label = new Label($label);

        return $this;
    }

    public function fieldWidth($width)
    {
        $this->getPrimaryControl()->fieldWidth = $this->normalizeWidth($width);

        return $this;
    }

    abstract public function render();

    public function __toString()
    {
        return $this->render();
    }

    protected function beforeRender()
    {
        return true;
    }

    protected function renderAttributes()
    {
        $result = '';
        foreach ($this->attributes as $attribute => $value) {

            if (!in_array($attribute,$this->fillable) && !starts_with('data-', $attribute)) {
                continue;
            }

            @$result .= " {$attribute}=\"{$value}\"";
        }

        return $result;
    }

    protected function normalizeWidth($width)
    {
        if (is_string($width)) {
            return $width . ' row';
        }

        if (is_numeric($width) && isset($this->widthTranslation[$width])) {
            return $this->widthTranslation[$width] . ' row';
        }

        return null;
    }

    public function buildRequiredTag()
    {
        return '<span class="text-danger"> * &nbsp;</span>';
    }

    protected function buildTip($tip)
    {
        return $tip ? '<p class="help-block" style="padding-top: 0px">' . $tip . '</p>' : '';
    }

    public function renderOption($option)
    {
        return $this->attributes($option);
    }

    public function __call($method, $params)
    {
        $params = count($params) ? $params : [$method];
        $params = array_merge([$method], $params);
        call_user_func_array([$this, 'attribute'], $params);

        return $this;
    }
}
